#ifndef OPENHITLS_KAE_MODES_H
#define OPENHITLS_KAE_MODES_H

#include "kaev1_memory.h"
#include <bsl_params.h>
#include <crypt_algid.h>
#include <crypt_eal_cipher.h>
#include <wd.h>
#include <wd_cipher.h>

#define SM4_BLOCK_NUM  4
#define SM4_KEY_SIZE   16
#define SM4_BLOCK_SIZE 16

#define AES128_BLOCK_NUM  4
#define AES128_KEY_SIZE   16
#define AES128_BLOCK_SIZE 16

#define AES192_BLOCK_NUM  4
#define AES192_KEY_SIZE   24
#define AES192_BLOCK_SIZE 16

#define AES256_BLOCK_NUM  4
#define AES256_KEY_SIZE   32
#define AES256_BLOCK_SIZE 16

#define CIPHER_BLOCK_NUM  4
#define CIPHER_BLOCK_SIZE (272 * 1024)
#define CIPHER_CACHE_SIZE 256

#define CIPHER_KEY_SIZE 64

extern KaeQueuePoolHead *gModesNodePool;

typedef struct {
    CRYPT_EAL_CipherCtx *ecbCtx;
    uint8_t *key;
    uint32_t keyLen;
    uint8_t *iv;
    uint32_t countNum;
} XTS_ECB;

typedef struct KAE_Mode_Ctx {
    struct wd_queue *queue;
    struct wd_queue_mempool *pool;
    struct wcrypto_cipher_ctx_setup setup;
    struct wcrypto_cipher_op_data opData;
    void *cipherCtx;
    KaeQueueDataEntry *entry;
    uint8_t block[CIPHER_CACHE_SIZE];
    uint8_t key[CIPHER_KEY_SIZE];
    uint32_t keySize;
    uint32_t cipherSize;
    uint32_t remain;
    int32_t pad;
    int32_t algId;
    XTS_ECB *xtsEcb;
} KAE_Mode_Ctx;

int WdModesInitQnodePool(void);

int WdModesDestroyQnodePool(void);

KAE_Mode_Ctx *KAE_Mode_NewCtx(int32_t algId);

int32_t KAE_Mode_InitCtx(KAE_Mode_Ctx *ctx, const uint8_t *key, uint32_t keyLen, const uint8_t *iv, uint32_t ivLen,
                         const BSL_Param *param, bool enc);

int32_t KAE_Mode_Update(KAE_Mode_Ctx *ctx, const uint8_t *in, uint32_t inLen, uint8_t *out, uint32_t *outLen);

int32_t KAE_Mode_Final(KAE_Mode_Ctx *ctx, uint8_t *out, uint32_t *outLen);

int32_t KAE_Mode_Ctrl(KAE_Mode_Ctx *ctx, int32_t cmd, void *val, uint32_t valLen);

int32_t KAE_Mode_Deinit(KAE_Mode_Ctx *ctx);

void KAE_Mode_Free(KAE_Mode_Ctx *ctx);

#endif